package nsu.edu.zsq.service.impl.sys;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;
import nsu.edu.zsq.bean.Course;
import nsu.edu.zsq.bean.CourseExample;
import nsu.edu.zsq.bean.CourseExample.Criteria;
import nsu.edu.zsq.bean.SchMajor;
import nsu.edu.zsq.bean.SchMajorExample;
import nsu.edu.zsq.bean.SchOrg;
import nsu.edu.zsq.bean.SchOrgExample;
import nsu.edu.zsq.common.RequestHolder;
import nsu.edu.zsq.dao.CourseMapper;
import nsu.edu.zsq.dao.SchMajorMapper;
import nsu.edu.zsq.dao.SchOrgMapper;
import nsu.edu.zsq.exception.ParamException;
import nsu.edu.zsq.param.PageQuery;
import nsu.edu.zsq.service.sys.CourseService;
import nsu.edu.zsq.service.sys.SysLogService;
import nsu.edu.zsq.util.BeanValidator;
import nsu.edu.zsq.util.ExcelUtil;
import nsu.edu.zsq.util.SchOrgUtil;

/** 
* Description: 学校课程的service实现类<br>
*/
@Slf4j
@Service
public class CourseServiceImpl implements CourseService {
    
    @Autowired
    private SchMajorMapper schMajorMapper;
    @Autowired
    private SchOrgMapper schOrgMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private SysLogService sysLogService;

    @Override
    public Course getCourse(int courseId) {
        Course course = courseMapper.selectByPrimaryKey(courseId);
        return course;
    }
    
    @Override
    public String listSchOrgWithMajorTree() {
        SchMajorExample schMajorexample = new SchMajorExample();
        List<SchMajor> listSchMajor = schMajorMapper.selectByExample(schMajorexample);
        SchOrgExample schOrgexample = new SchOrgExample();
        List<SchOrg> listSchOrg = schOrgMapper.selectByExample(schOrgexample);
        String schOrgWithMajorToTree = SchOrgUtil.schOrgWithMajorToTree(listSchMajor, listSchOrg);
        return schOrgWithMajorToTree;
    }

    @Override
    public PageInfo<Course> listCourseWithPage(String majorNo, PageQuery pageQuery) {
        // 所有课程
        String allCourse = "0";
        PageHelper.startPage(pageQuery.getPageNum(),pageQuery.getPageSize());
        CourseExample example = new CourseExample();
        // 不展示
        Criteria createCriteria = example.createCriteria();
        createCriteria.andTypeNotEqualTo(3);
        // 根据排序号，降序
        example.setOrderByClause("sort desc");
        List<Course> listCourse = null;
        if (allCourse.equals(majorNo)) {
            listCourse = courseMapper.selectByExample(example);
        } else {
            createCriteria.andMajorNoEqualTo(majorNo);
            listCourse = courseMapper.selectByExample(example);
        }
        PageInfo<Course> pageInfo = new PageInfo<Course>(listCourse, pageQuery.getNavigatePages());
        return pageInfo;
    }
    
    @Override
    public PageInfo<Course> listPublicWithPage(PageQuery pageQuery) {
        PageHelper.startPage(pageQuery.getPageNum(),pageQuery.getPageSize());
        CourseExample example = new CourseExample();
        example.createCriteria().andTypeEqualTo(3);
        // 根据排序号，降序
        example.setOrderByClause("sort desc");
        List<Course> listCourse = courseMapper.selectByExample(example);
        PageInfo<Course> pageInfo = new PageInfo<Course>(listCourse, pageQuery.getNavigatePages());
        return pageInfo;
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importCourseFromExcel(MultipartFile excelFile) {
        List<Course> listCourse = ExcelUtil.importExcel(excelFile, 1, 1, Course.class);
        // TODO:对导入数据进行校验
        saveBatchCourse(listCourse);
        log.info("导入学校专业数据一共【{}】条",listCourse.size());
    }
    
    @Override
    public void exportCourseToExcel(HttpServletResponse response) {
        CourseExample example = new CourseExample();
        List<Course> listCourse = courseMapper.selectByExample(example);
        // 导出操作
        ExcelUtil.exportExcel(listCourse,"课程列表","Sheet1",Course.class,"学校课程.xlsx",response);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveBatchCourse(List<Course> listCourse) {
        // 因导入的数据量过大，所以不记录全部日志内容，这里使用自定义的操作日志内容
        Map<String, Object> map = new HashMap<String, Object>(listCourse.size());
        map.put("数据量", listCourse.size());
        List<String> listCourseNo = new ArrayList<String>();
        for (Course course : listCourse) {
            if (checkCourseNoExist(course.getCourseNo())) {
                throw new ParamException("存在相同的课程代码");
            }
            course.setIsFinish(0);
			/*
			 * course.setOperator(RequestHolder.getCurrentSysUser().getAccount());
			 * course.setOperatorTime(new Date());
			 */
            // TODO：是否存在相同的课程代码
            // 1.添加课程
            courseMapper.insertSelective(course);
            listCourseNo.add(course.getCourseNo());
        }
        map.put("课程代码", listCourseNo);
		/*
		 * // 2.添加日志 String instruction = "课程管理-批量导入";
		 * sysLogService.saveSysLogBySysUser(null, map, instruction);
		 */
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteCourse(int courseId) {
        Course before = getCourse(courseId);
        // 1.单个删除
        courseMapper.deleteByPrimaryKey(courseId);
        
		/*
		 * // 2.添加日志 String instruction = "课程管理-单个删除";
		 * sysLogService.saveSysLogBySysUser(before, null, instruction);
		 */
        
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchCourse(int[] courseId) {
        List<Course> before = new ArrayList<Course>();
        // 1.批量删除
        for (int i : courseId) {
            Course course = getCourse(i);
            before.add(course);
            courseMapper.deleteByPrimaryKey(i);
        }
		/*
		 * // 2.添加日志 String instruction = "课程管理-批量删除";
		 * sysLogService.saveSysLogBySysUser(before, null, instruction);
		 */
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveCourse(Course course) {
        BeanValidator.check(course);
        if (checkCourseNoExist(course.getCourseNo())) {
            throw new ParamException("该课程代码已经存在");
        }
		/*
		 * course.setIsFinish(0);
		 * course.setOperator(RequestHolder.getCurrentSysUser().getAccount());
		 * course.setOperatorTime(new Date());
		 */
        // 添加课程
        courseMapper.insertSelective(course);
		/*
		 * // 2.添加日志 String instruction = "课程管理-添加课程";
		 * sysLogService.saveSysLogBySysUser(null, course, instruction);
		 */
    }


    /**
     * 根据课程代码检查该课程是否存在
     * @param courseNo 课程代码
     * @return boolean true:存在 false：存在
     */
    private boolean checkCourseNoExist(String courseNo) {
        return courseMapper.countByCourseNo(courseNo) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCourse(Course course) {
        Course before = getCourse(course.getId());
        if (!before.getCourseNo().equals(course.getCourseNo())) {
            if (checkCourseNoExist(course.getCourseNo())) {
                throw new ParamException("该课程代码已经存在");
            }
        }
        Course after = new Course();
        BeanUtils.copyProperties(before, after);
        after.setCourseName(course.getCourseName());
        after.setCourseNo(course.getCourseNo());
        after.setCredit(course.getCredit());
        after.setSort(course.getSort());
        after.setType(course.getType());
        after.setStartTime(course.getStartTime());
		/*
		 * after.setOperator(RequestHolder.getCurrentSysUser().getAccount());
		 * after.setOperatorTime(new Date());
		 */
        
        // 1.更新课程
        courseMapper.updateByPrimaryKeySelective(after);
		/*
		 * // 2.添加日志 String instruction = "课程管理-更新课程";
		 * sysLogService.saveSysLogBySysUser(before, after, instruction);
		 */
    }

}
